/* Cell Based Lighting */

#include "LightUtils.hlsl"

// Thread Count
#define NUM_THREADS_X	16
#define NUM_THREADS_Y	16
#define NUM_THREADS_Z	1
#define MAX_PASSES		8

// Post Buffer
cbuffer PostBuffer : register(b0)
{
	float3	WaterOverlayColor;
	float	WaterOverlayStrength;
	uint	WaterOverlayEnabled;
	float	WaterVignetteRadius;
	uint	ScreenWidth;
	uint	ScreenHeight;
	float3	CameraPosition;
	float	FogNear;
	float3	FogColor;
	float	FogFar;
	float3	FogSecondColor;
	uint	FogEnabled;
}

// Compute Input
struct ComputeInput
{
	uint3	GroupID				: SV_GroupID;
	uint	GroupIndex			: SV_GroupIndex;
	uint3	GroupThreadID		: SV_GroupThreadID;
	uint	GroupThreadIndex	: SV_DispatchThreadID;
};

// Textures
Texture2D<float4>	g_RawTarget3D			: register(t0);
Texture2D<float4>	g_PositionTexture		: register(t1);
Texture2D<float4>	g_NormalTexture			: register(t2);
Texture2D<float4>	g_AlbedoTexture			: register(t3);
Texture2D<float4>	g_AmbientTexture		: register(t4);
Texture2D<float>	g_DepthStencil			: register(t5);

RWTexture2D<float4> g_OutputTexture		: register(u0);

// Post Fog
float4 PostFog(float4 inputColor, uint2 pixelIndex)
{
	float3 worldPos = g_PositionTexture[pixelIndex].xyz;
	float camDistance = distance(worldPos, CameraPosition);

	float alpha = max(0.0f, (camDistance - FogNear)) / (FogFar - FogNear);
	alpha = saturate(alpha);
	alpha = pow(alpha, 2);

	float3 fogColor = lerp(FogColor, FogSecondColor, alpha);
	float4 clr = lerp(inputColor, float4(fogColor, 1.0f), alpha);

	return clr;
}

// Post Water
float4 PostWaterOverlay(float4 inputColor, uint2 pixelIndex)
{
	// Calculate Water Fade
	float4 clr = float4(0.0f, 0.0f, 0.0f, 1.0f);
	clr.xyz = (inputColor.xyz * (1.0f - WaterOverlayStrength)) + (WaterOverlayColor * WaterOverlayStrength);
	clr.a = inputColor.a;

	// Calculate the Vignete Overlay
	float2 uv = float2((float)pixelIndex.x / ScreenWidth, (float)pixelIndex.y / ScreenHeight);
	float dist = distance(uv, float2(0.5f, 0.5f));
	clr.xyz *= ((1.0f - dist) * WaterVignetteRadius);

	return clr;
}

[numthreads(NUM_THREADS_X, NUM_THREADS_Y, NUM_THREADS_Z)]
void main(ComputeInput input)
{
	// Compute to Which pixel we correspond
	uint2 PixelIndex = uint2(0, 0);
	PixelIndex.x = (input.GroupID.x * NUM_THREADS_X) + input.GroupThreadID.x;
	PixelIndex.y = (input.GroupID.y * NUM_THREADS_Y) + input.GroupThreadID.y;

	// Sample the Pixels
	float4 postColor = g_RawTarget3D[PixelIndex];
	if (FogEnabled > 0)
		postColor = PostFog(postColor, PixelIndex);
	if (WaterOverlayEnabled > 0)
		postColor = PostWaterOverlay(postColor, PixelIndex);
	
	// Output the Color to the Texture
	g_OutputTexture[PixelIndex] = postColor;
}